/*
 * ConceptualRentalDAO.java
 *
 * Created on March 22, 2007, 1:45 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package edu.byu.isys413.group1E.data;

import edu.byu.isys413.group1E.handlers.*;
import java.sql.*;
import java.util.ArrayList;

/**
 * @author Jon Tehero
 */
public class ConceptualRentalDAO extends ConceptualDAO{
    private static ConceptualRentalDAO instance = null;
//******************************************************************************
//   SINGLETON PATTERN
//******************************************************************************
    /** Creates a new instance of ConceptualRentalDAO */
    public ConceptualRentalDAO() {
    }
    
    /**Retrieves an instance of the TransactionDAO object**/
    public static synchronized ConceptualRentalDAO getInstance() {
        if (instance == null) {
            instance = new ConceptualRentalDAO();
        }
        return instance;
    }
    
//******************************************************************************
//   CREATE
//******************************************************************************
    /**
     * @throws java.lang.Exception
     * @return
     */
    public ConceptualRentalBO create() throws Exception{
        String id = GUID.generate();
        ConceptualRentalBO bo = new ConceptualRentalBO(id);
        Cache c = Cache.getInstance();
        c.put(bo.getProductID(), bo);
        return bo;
    }
    
//******************************************************************************
//   READ - Incorporates 2 Read Methods (1 for external use, 1 for internal),
//          and 1 ReadAll Method
//******************************************************************************
    /**
     *
     * @param id
     * @throws java.sql.SQLException
     * @throws edu.byu.isys413.group1E.DataException
     * @throws edu.byu.isys413.group1E.ConnectionPoolException
     * @return
     */
    public ProductBO read(String id) throws SQLException, DataException, ConnectionPoolException {
        // check to see if id in the cache
        Cache c = Cache.getInstance();
        ConceptualRentalBO conceptualRental = null;
                
        //otherwise, get it from the database
        try {
            Connection conn = ConnectionPool.getInstance().get();             // retrieve a database connection from the pool
            conceptualRental = (ConceptualRentalBO)this.read(id, conn);                                              // call read with a connection
            conn.commit();
            ConnectionPool.getInstance().release(conn);                       // release the connection
        }catch (SQLException e) {
            //rollback
            throw new DataException("Could not retrieve record for id = " + id, e);
        }catch (ConnectionPoolException x) {
            //rollback
            throw new ConnectionPoolException("Could not establish connection to database.", x);
        }
        
        // release the connection back to the pool
        return conceptualRental;
    }
    
    /**
     *
     * @param id
     * @param conn
     * @throws java.sql.SQLException
     * @throws edu.byu.isys413.group1E.DataException
     * @throws edu.byu.isys413.group1E.ConnectionPoolException
     * @return
     */
    public synchronized ProductBO read(String id, Connection conn) throws SQLException, DataException, ConnectionPoolException {
        // check to see if id in the cache
        Cache c = Cache.getInstance();
        ConceptualRentalBO conceptualRental = null;
        //put it to the cache so the super.read can get it
        conceptualRental = new ConceptualRentalBO(id);
        c.put(id, conceptualRental);
        // if not in the cache, get a result set from
        // a SELECT * FROM table WHERE id=guid
        conceptualRental = (ConceptualRentalBO)super.read(id, conn);
        
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT * FROM Conceptual_Rental WHERE ProductID = '" + id + "'");
        conn.commit();
        
        //build the object from the result set
        if (rs.next()) {
            conceptualRental.setPricePerDay(rs.getDouble("Price_Per_Day"));
            conceptualRental.setPricePerDay(rs.getDouble("Replacement_Price"));
            conceptualRental.setPricePerDay(rs.getInt("MaxTimesRented"));
            conceptualRental.setPricePerDay(rs.getDouble("LateFeePerDay"));
            // save to the cache
            c.put(conceptualRental.getProductID(), conceptualRental);
        }else{
            throw new DataException("Object was not found in the database.");
        }
        stmt.close(); ConnectionPool.getInstance().release(conn);
        // return the BO
        return conceptualRental;
    }    
    /**
     *
     * @throws edu.byu.isys413.group1E.DataException
     * @throws java.sql.SQLException
     * @throws edu.byu.isys413.group1E.ConnectionPoolException
     * @return
     */
    public synchronized ArrayList<ProductBO> readAllCRs() throws DataException, SQLException, ConnectionPoolException{
        ArrayList<ProductBO> list = new ArrayList<ProductBO>();
        //now build the query
        String query = "SELECT * FROM Conceptual_Rental";
        Connection conn = ConnectionPool.getInstance().get();
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(query);
        conn.commit();
        
        //extract the elements from the result set and build a list of results
        //build the object from the result set
        while (rs.next()) {
            ConceptualRentalBO conceptualRental = new ConceptualRentalBO(rs.getString("ProductID"));
            Cache.getInstance().put(rs.getString("ProductID"), conceptualRental);
            super.read(rs.getString("ProductID"), conn);
            //conceptualRental = (ConceptualRentalBO)super.read(rs.getString("ProductID"), conn);
            conceptualRental.setPricePerDay(rs.getDouble("Price_Per_Day"));
            conceptualRental.setPricePerDay(rs.getDouble("Replacement_Price"));
            conceptualRental.setPricePerDay(rs.getInt("MaxTimesRented"));
            conceptualRental.setPricePerDay(rs.getDouble("LateFeePerDay"));
            conceptualRental.setAlreadyInDB(true);
            conceptualRental.setDirty(false);
            // save to the list
            list.add(conceptualRental);
        }//while
        stmt.close();
        ConnectionPool.getInstance().release(conn);
        return list;
    }
    
    public synchronized ArrayList<ProductBO> getRentalCategoriesFromConceptualRental(String productID) throws DataException, SQLException, ConnectionPoolException{
        
        ArrayList<ProductBO> list = new ArrayList<ProductBO>();
        //productID
        //Builds the query
        
        String query = "SELECT * FROM ConceptualRental";
        
        Connection conn = ConnectionPool.getInstance().get();
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(query);
        conn.commit();
       
        
//extract the elements from the result set and build a list of results
//build the object from the result set
        while (rs.next()) {
            ConceptualRentalBO conceptualRental = new ConceptualRentalBO(rs.getString("ProductID"));
            Cache.getInstance().put(rs.getString("ProductID"), conceptualRental);
            conceptualRental = (ConceptualRentalBO)super.read(rs.getString("ProductID"), conn);
            conceptualRental.setPricePerDay(rs.getDouble("PricePerDay"));
            conceptualRental.setPricePerDay(rs.getDouble("ReplacementPrice"));
            conceptualRental.setPricePerDay(rs.getInt("MaxTimesRented"));
            conceptualRental.setPricePerDay(rs.getDouble("LateFeePerDay"));
            conceptualRental.setAlreadyInDB(true);
            conceptualRental.setDirty(false);
            
// save to the list
            list.add(conceptualRental);
        }//while
        
        stmt.close();
        ConnectionPool.getInstance().release(conn);
        return list;
    }

//    public synchronized ArrayList<String> getRentalCategoriesFromConceptualRental(String productID) throws DataException, SQLException, ConnectionPoolException{
//        
//        ArrayList<ProductBO> list = new ArrayList<ProductBO>();
//        // productID
//        //Builds the query
//        
//        String query = "SELECT * FROM ConceptualRental";
//        
//        Connection conn = ConnectionPool.getInstance().get();
//        Statement stmt = conn.createStatement();
//        ResultSet rs = stmt.executeQuery(query);
//        conn.commit();
//        
//        
//        //extract the elements from the result set and build a list of results
//        //build the object from the result set
//        while (rs.next()) {
//            ConceptualRentalBO conceptualRental = new ConceptualRentalBO(rs.getString("ProductID"));
//            Cache.getInstance().put(rs.getString("ProductID"), conceptualRental);
//            conceptualRental = (ConceptualRentalBO)super.read(rs.getString("ProductID"), conn);
//            conceptualRental.setPricePerDay(rs.getDouble("PricePerDay"));
//            conceptualRental.setPricePerDay(rs.getDouble("ReplacementPrice"));
//            conceptualRental.setPricePerDay(rs.getInt("MaxTimesRented"));
//            conceptualRental.setPricePerDay(rs.getDouble("LateFeePerDay"));
//            conceptualRental.setAlreadyInDB(true);
//            conceptualRental.setDirty(false);
//            // save to the list
//            list.add(conceptualRental);
//        }//while
//        
//        stmt.close();
//        ConnectionPool.getInstance().release(conn);
//        return list;
//    }
    

//******************************************************************************
//   UPDATE - Incorporates 1 Insert, & 1 Update methods
//******************************************************************************
    synchronized void insert(ProductBO bo, Connection conn) throws SQLException, DataException, ConnectionPoolException {
//update the DB
        ConceptualRentalBO BO = (ConceptualRentalBO)bo;
        
//        super.save(BO, conn);
        
        PreparedStatement pstmt = conn.prepareStatement("INSERT INTO ConceptualRental (PRODUCTID, Price_Per_Day, " +
                "Replacement_Price, Max_Times_Rent, LateFeePerDay) VALUES (?, ?, ?, ?, ?)");
        
        pstmt.setString(1, BO.getProductID());
        pstmt.setDouble(2, BO.getPricePerDay());
        pstmt.setDouble(3, BO.getReplacementPrice());
        pstmt.setInt(4, BO.getMaxTimesRented());
        pstmt.setDouble(5, BO.getLateFeePerDay());
        pstmt.execute();
        pstmt.close();
        BO.setAlreadyInDB(true);
// tell the object that it's now in the db (so we call update next time not insert)
        BO.setAlreadyInDB(true);
    }//end insert
    
    /**
     *
     * @param bo
     * @param conn
     * @throws java.sql.SQLException
     * @throws edu.byu.isys413.group1E.DataException
     * @throws edu.byu.isys413.group1E.ConnectionPoolException
     */
    protected void update(ProductBO bo, Connection conn) throws SQLException, DataException, ConnectionPoolException{
        //update the DB
        ConceptualRentalBO BO = (ConceptualRentalBO)bo;
        
//        super.save(BO, conn);
        
        PreparedStatement pstmt = conn.prepareStatement("UPDATE ConceptualRental SET Price_Per_Day = ?, " +
                "Replacement_Price = ?, Max_Times_Rented= ?, LateFeePerDay = ? WHERE ProductID = ?");
        
        pstmt.setDouble(1, BO.getPricePerDay());
        pstmt.setDouble(2, BO.getReplacementPrice());
        pstmt.setInt(3, BO.getMaxTimesRented());
        pstmt.setDouble(4, BO.getLateFeePerDay());
        pstmt.setString(5, BO.getProductID());
        pstmt.execute();
        pstmt.close();
        BO.setAlreadyInDB(true);
    }// end update
//******************************************************************************
//   DELETE - Does not incorporate any methods
//******************************************************************************
    /**
     * Any and all delete methods were intentionally left out of this
     * program becuase we specifically DO NOT want to give the users the
     * ability to delete ANYTHING.  All records will remain on file.
     * Archival options would recommended over deleting.
     **/
}